package com.feng.oauth2jwt;

import com.alibaba.druid.pool.DruidDataSource;
import com.feng.oauth2jwt.myauthen.MyJwtTokenStore;
import com.feng.oauth2jwt.oauth.domain.oauth.CustomJdbcClientDetailsService;
import com.feng.oauth2jwt.oauth.domain.oauth.CustomJdbcTokenStore;
import com.feng.oauth2jwt.oauth.infrastructure.OauthUserApprovalHandler;
import com.feng.oauth2jwt.oauth.infrastructure.jdbc.SOSAuthorizationCodeServices;
import com.feng.oauth2jwt.oauth.service.UserService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationManager;
import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter;
import org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService;
import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint;
import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.util.Assert;


/**
 * @author feng
 * @description TODO
 * @date 2019/1/10 16:31
 */
@Configuration
@EnableAuthorizationServer
public class MyOauthServer extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private DruidDataSource dataSource;
    @Autowired
    private SOSAuthorizationCodeServices sosAuthorizationCodeServices;
    @Autowired
//    @Qualifier("authenticationManagerBean")
    private AuthenticationManager authenticationManager;
    @Autowired
    @Qualifier("ouathUserService")
    private UserService ouathUserService;

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(tokenStore()).accessTokenConverter(accessTokenConverter()).authenticationManager(authenticationManager);
//        endpoints.userDetailsService(ouathUserService);
//        endpoints.tokenServices(getTokenServices());
//        endpoints.authorizationCodeServices(sosAuthorizationCodeServices);
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
       clients.jdbc(dataSource);
    }


//    @Bean
//    OAuth2AuthenticationManager getAuthenticationManager(){
//        OAuth2AuthenticationManager authenticationManager = new OAuth2AuthenticationManager();
//        authenticationManager.setTokenServices(getTokenServices());
//        authenticationManager.setClientDetailsService(getCustomJdbcClientDetailsService());
//        return authenticationManager;
//
//    }


//
    @Bean
    ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilter(){
        ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilter = new ClientCredentialsTokenEndpointFilter();
        clientCredentialsTokenEndpointFilter.setAuthenticationManager(authenticationManager);
        clientCredentialsTokenEndpointFilter.setContinueChainBeforeSuccessfulAuthentication(false);
        clientCredentialsTokenEndpointFilter.setAuthenticationEntryPoint(oAuth2AuthenticationEntryPoint());
        return clientCredentialsTokenEndpointFilter;
    }

//    @Bean
//    OAuth2AuthenticationEntryPoint getOauth2AuthenticationEntryPoint(){
//
//
//        return new OAuth2AuthenticationEntryPoint();
//    }


    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
       security.allowFormAuthenticationForClients();
       security.authenticationEntryPoint(oAuth2AuthenticationEntryPoint());
       security.tokenKeyAccess("permitAll()")
                .checkTokenAccess("isAuthenticated()");

    }

    @Bean
    @Primary
    DefaultTokenServices getTokenServices(){
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenStore(tokenStore());
        defaultTokenServices.setSupportRefreshToken(true);
        defaultTokenServices.setClientDetailsService(getCustomJdbcClientDetailsService());
        return defaultTokenServices;
    }
    @Bean
    public MyJwtTokenStore tokenStore() {
        MyJwtTokenStore jwtTokenStore = new MyJwtTokenStore(accessTokenConverter());
        return jwtTokenStore;
    }
    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey(JwtUtils.ssoAppPrivateKey);
        converter.setVerifierKey(JwtUtils.ssoAppPublicKey);
        return converter;
    }

    @Bean
    SOSAuthorizationCodeServices getJdbcAuthorizationCodeServices(){

        return new SOSAuthorizationCodeServices(dataSource);
    }

    @Bean
    DefaultOAuth2RequestFactory getDefaultOAuth2RequestFactory(){
        return new DefaultOAuth2RequestFactory(getCustomJdbcClientDetailsService());
    }

    @Bean
    OauthUserApprovalHandler getTokenStoreUserApprovalHandler(){
        OauthUserApprovalHandler tokenStoreUserApprovalHandler = new OauthUserApprovalHandler();
        tokenStoreUserApprovalHandler.setClientDetailsService(getCustomJdbcClientDetailsService());
        tokenStoreUserApprovalHandler.setTokenStore(tokenStore());
        tokenStoreUserApprovalHandler.setRequestFactory(getDefaultOAuth2RequestFactory());
        return tokenStoreUserApprovalHandler;
    }

    @Bean
    CustomJdbcClientDetailsService getCustomJdbcClientDetailsService(){
        return new CustomJdbcClientDetailsService(dataSource);
    }
    @Bean
    ClientDetailsUserDetailsService clientDetailsUserDetailsService(){
        return new ClientDetailsUserDetailsService(getCustomJdbcClientDetailsService());
    }
    @Bean
    OAuth2AuthenticationEntryPoint oAuth2AuthenticationEntryPoint() {
        final OAuth2AuthenticationEntryPoint entryPoint = new OAuth2AuthenticationEntryPoint();
//        entryPoint.setRealmName("oauth/client");
        entryPoint.setTypeName("Basic");
        return entryPoint;
    }


}
